package com.hax2max.control;

import java.security.acl.Owner;
import java.util.ArrayList;
import java.util.HashMap;

import android.provider.Settings.System;
import android.util.Log;

import com.hax2max.R;
import com.hax2max.control.externalclient.ClientFactory;
import com.hax2max.control.externalclient.IExternalClient;
import com.hax2max.model.ExternalData;
import com.hax2max.control.FriendStalkerException;

public class CommunicationConnector {

	private static CommunicationConnector instance;
	private static final String TAG = "CommunicationConnector";
	HashMap<Integer,IExternalClient> systems; 
	
	public enum ComunnicationSystemType{
		Local,
		External
	}
	
	
	private CommunicationConnector() {
		systems = new HashMap<Integer, IExternalClient>(2);
	}
	
	/**
	 * Singelton constructor.
	 * @return instance of CommunicationConnector
	 */
	public static CommunicationConnector getInstance() {
		if(instance == null)
			instance = new CommunicationConnector();
		return instance;
	}
	
	/**
	 * Updates all the statuses for each ExternalData that is provided.
	 * statusText of each object is updated with the new status.
	 * @param exdList
	 * @return ra
	 * @throws FriendStalkerException.IExternalClient 
	 */
	public ExternalData[] getAllStatus(ArrayList<ExternalData> exdList) throws FriendStalkerException {		
		ExternalData[] ra = new ExternalData[exdList.size()];
		
		for(int i = 0; i < exdList.size() ;i++) {
			
			Log.e(TAG,  
					"try to get status from " + exdList.get(i).application + "\n" +
					"userId = " + exdList.get(i).userId + "\n");
			try {
				ra[i] = getStatus(exdList.get(i));
				Log.e(TAG, "got new status AppID: " + exdList.get(i).application + " for user " +exdList.get(i).username + " status message: "+ exdList.get(i).statusText );
			} catch( Exception e) {
				Log.e(TAG, "getStatus "+ exdList.get(i).application + " " + exdList.get(i).username +" " + "  caught exception: "+ e.getMessage());
				throw new FriendStalkerException(R.string.Exception_FriendStalker_IExternalClientInvalidConnectionError); //TODO change to correct exception ID
			}
		}
		exdList = null;
		return ra;
	}
	
	
	/**
	 * Get's the status of the user on the specified system.
	 * statusText in the provided exd is changed.
	 * @param exd
	 * @return exd
	 * @throws FriendStalkerException.IExternalClient 
	 */
	public ExternalData getStatus(ExternalData exd) throws FriendStalkerException.IExternalClient {		
		
		IExternalClient ec = systems.get(exd.application);		
		if(ec == null) {
			Log.e(TAG, "no client appID  "+ exd.application + " was logged in ");
			return exd;			
		}
		return ec.loadData(exd);							
	}
	
	/**
	 * user for logging in a client
	 * @param appId
	 * @return true if successful
	 * @throws FriendStalkerException.IExternalClient
	 */
	
	public boolean loginClient(int appId) throws FriendStalkerException.IExternalClient{
		systems.put(appId, ClientFactory.getClient(appId));
		return true;
	}
	
	/**
	 * logs the user out of the system and clears all the logged in data
	 */
	public void logOutClient() {
		systems = new HashMap<Integer, IExternalClient>(2);
	}
	
	/**
	 * Updates the status at an external system. Takes the 
	 * external client connector depending on the applicationId provided.
	 * Sends the statusText as new status to the system and using the userid and password 
	 * to login to that system. 
	 * @param ExternalData exd 
	 * @return true if update was succesfull
	 * @throws FriendStalkerException.IExternalClient 
	 */
	public boolean updateStatus(ExternalData exd) throws FriendStalkerException.IExternalClient {
		Log.e(TAG, "trying to send status: " + exd.statusText + "\nusername " + exd.login + 
				"appId: " + exd.application);
		IExternalClient client = systems.get(exd.application);
		if(client != null)
		{
			
			return client.updateStatus(exd);
		}
		else 
			Log.e(TAG, "Could not find client... id: " + exd.application);
			return false;
	}
	
	public void changeLoginExternalClient(int appId, String username, String password) throws FriendStalkerException.IExternalClient
	{
		IExternalClient client = systems.get(appId);
		if(client != null)
			client = client.changeUserAndLogin(username, password);
		else
			client = ClientFactory.getClient(appId, username, password);
		Log.e(TAG, "put client id: " + appId  + " in systems");
		systems.put(appId, client); //oki!
	}
	
	public Object executeMethodExternalClient(int appId, String method, String ...parameters) throws FriendStalkerException.IExternalClient
	{
		IExternalClient client = systems.get(appId);
		if(client == null)
			throw new FriendStalkerException.IExternalClient(R.string.Exception_FriendStalker_IExternalClientNotLoggedIn);
		else 
			return client.callOtherMethod(method, parameters);
	}
}
